
// note: 有意思的类型
type LinkedList<T> = T & { next: LinkedList<T> };

interface Person {
  name: string;
}

// var people: LinkedList<Person>={
//   name:'ryan',
//
// };
// var s = people.name;
// var s = people.next.name;
// var s = people.next.next.name;
// var s = people.next.next.next.name;

// note: 字符串字面量类型
type Easing = "ease-in" | "ease-out" | "ease-in-out";
class UIElement {
  animate(dx: number, dy: number, easing: Easing) {
    if (easing === "ease-in") {
      // ...
    }
    else if (easing === "ease-out") {
    }
    else if (easing === "ease-in-out") {
    }
    else {
      // error! should not pass null or undefined.
    }
  }
}

let button = new UIElement();
button.animate(0, 0, "ease-in");
//button.animate(0, 0, "uneasy"); // error: "uneasy" is not allowed here


namespace 索引类型{
  // note: T[K] 对应K所属类型
  function pluck<T, K extends keyof T>(o: T, names: K[]): T[K][] {
    return names.map(n => o[n]);
  }

  interface Person {
    name: string;
    age: number;
  }
  let person: Person = {
    name: 'Jarid',
    age: 35
  };
  let strings: string[] = pluck(person, ['name']); // ok, string[]

  console.log(strings)
  //note: let personProps: keyof Person; // 'name' | 'age'
  //keyof Person是完全可以与 'name' | 'age'互相替换的。 不同的是如果你添加了其它的属性到 Person，
  // note: 变成只读的

  type ReadonlyEntity<T> = {
    readonly [P in keyof T]: T[P];
  }



  type PersonReadonly= ReadonlyEntity<Person>

  let personReadonly:PersonReadonly={
    name: 'Jarid',
    age: 35
  }
// personReadonly.name='wwwb'  error 不可修改

// note: 变成可选property
  type PartialEntity<T> = {
    [P in keyof T]?: T[P];
  }

  type  PersonPartial=PartialEntity<Person>

  //note: pick
  interface Todo {
    title: string;
    description: string;
    completed: boolean;
  }

  type TodoPreview = Pick<Todo, "title" | "completed">;

  const todo: TodoPreview = {
    title: "Clean room",
    completed: false,
  };

  //note: Record<Keys,Type>  相当于map
  interface PageInfo {
    title: string;
  }

  type Page = "home" | "about" | "contact";

  const nav: Record<Page, PageInfo> = {
    about: { title: "about" },
    contact: { title: "contact" },
    home: { title: "home" },
  };
  console.log(nav.about)

}

// note:omit

interface Todo {
  title: string;
  description: string;
  completed: boolean;
}

type TodoPreview = Omit<Todo, "description">; // { title: string; completed: boolean; }

const todo: TodoPreview = {
  title: "Clean room",
  completed: false,
};



//note:可实例化
interface CallMeWithNewToGetString {
  new (): string;
}

// 使用
declare const Foo: CallMeWithNewToGetString;
const bar = new Foo(); // bar 被推断为 string 类型

function logName(something: { name: string }) {
  console.log(something.name);
}

const person = { name: 'matt', job: 'being awesome' };
const animal = { name: 'cow', diet: 'vegan, but has milk of own specie' };
const randow = { note: `I don't have a name property` };

logName(person); // ok


//note:动态添加属性，索引签名

interface Developer {
  name: string;
  age?: number;
  [key: string]: any
}

let developer: Developer = { name: "semlinker" };
developer.age = 30;
developer.city = "XiaMen";
// record
interface Developer extends Record<string, any> {
  name: string;
  age?: number;
}


